package storage.log;

import java.util.Iterator;

import server.starDB;
import storage.file.Block;
import storage.file.Page;

public class LogMgr implements Iterable<BasicLogRecord>{

	private Page mypage = new Page();
	private Block currentblk;
	private String logfile;
    private int currentpos;
	public LogMgr(String file) {
		this.logfile = file;
        int size = starDB.fileMgr().size(file);
        if(size == 0) {
            appendBlock();
        } else {
            currentblk = new Block(logfile, size - 1);
            mypage.read(currentblk);
            currentpos = mypage.getInt(0) + 4;
        }
	}
    private void appendBlock() {
    	mypage.setInt(0, 0);
        currentpos = 4;
        currentblk = mypage.append(logfile);
    }
    
    public Iterator<BasicLogRecord> iterator() {
    	flush();
    	return new LogIterator(currentblk);
    }
    
    public synchronized int append(Object[] rec) {
    	int size = 4;
    	for(Object obj : rec) {
    		size += size(obj);
    	}
    	if(currentpos + size >= Page.BLOCK_SIZE) {
    		flush();
    		appendBlock();
    	}
    	for(Object obj : rec) {
    		appendVal(obj);
    	}
    	int last = mypage.getInt(0);
    	mypage.setInt(currentpos, last);
    	mypage.setInt(0, currentpos);
    	currentpos += 4;
    	return currentblk.getBlkNum();
    }
    
    private void appendVal(Object obj) {
    	if(obj instanceof String) {
    		String s = (String)obj;
    		mypage.setString(currentpos, s);
    	} else {
    		int t = (Integer)obj;
    		mypage.setInt(currentpos, t);
    	}
    	currentpos += size(obj);
    }
    
    private int size(Object obj) {
    	if(obj instanceof String) {
    		String s = (String)obj;
    		return Page.STR_SIZE(s.length());
    	} else {
    		return 4;
    	}
    }
	
	public void flush(int lsn) {
	      if (lsn >= currentblk.getBlkNum())
	         flush();
	}
	
	private void flush() {
	      mypage.write(currentblk);
	 }
}
